﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Analysis;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;

namespace YArchitech.Revit
{
	public static class RevitDocumentExtension
	{
		public static void MirrorElements(Document inputDoc, ICollection<ElementId> inputElementId, Plane inputPlan, bool ifNonCopy)
		{
			ElementTransformUtils.MirrorElements(inputDoc, inputElementId, inputPlan);
			inputDoc.Delete(inputElementId);
		}

		public static double GetTextWidthFactory()
		{
			return 0.48;
		}

		public static double GetVersionTextWidthFactory()
		{
			return 1.65;
		}

		public static Element GetElementById(this Document revitDocument, ElementId elementId)
		{
			return revitDocument.GetElement(elementId);
		}

		public static double GetHYOutDoorAirPerPerson(this Zone zone)
		{
			return zone.OutDoorAirPerPerson;
		}

		public static Curve HYCreateEllipse(XYZ center, double xRadius, double yRadius, XYZ xAxis, XYZ yAxis, double startParameter, double endParameter)
		{
			return Ellipse.Create(center, xRadius, yRadius, xAxis, yAxis, startParameter, endParameter);
		}

		public static void HYSetVisibility(this View view, Category category, bool visible)
		{
			view.SetVisibility(category, visible);
		}

		public static Group CreatYJKGroup(this Document revitDocument, ElementSet elemSet)
		{
			ICollection<ElementId> collection = new List<ElementId>();
			foreach (object obj in elemSet)
			{
				Element element = (Element)obj;
				collection.Add(element.Id);
			}
			return revitDocument.Create.NewGroup(collection);
		}

		public static Arc CreatYJKArc(this Document revitDocument, XYZ center, double radius, double startAngle, double endAngle, XYZ xAxis, XYZ yAxis)
		{
			Arc result = null;
			try
			{
				result = Arc.Create(center, radius, startAngle, endAngle, xAxis, yAxis);
			}
			catch
			{
			}
			return result;
		}

		public static Arc CreatYJKArc(this Document revitDocument, Plane plane, double radius, double startAngle, double endAngle)
		{
			Arc result = null;
			try
			{
				result = Arc.Create(plane, radius, startAngle, endAngle);
			}
			catch
			{
			}
			return result;
		}

		public static Arc CreatYJKArc(this Document revitDocument, XYZ startPnt, XYZ endPnt, XYZ radianPnt)
		{
			return Arc.Create(startPnt, endPnt, radianPnt);
		}

		public static Arc CreatYJKArc(this Application revitApp, XYZ startPnt, XYZ endPnt, XYZ radianPnt)
		{
			return Arc.Create(startPnt, endPnt, radianPnt);
		}

		public static DetailCurve CreatYJKDetailCurve(this Document revDoc, Curve curve)
		{
			return revDoc.Create.NewDetailCurve(revDoc.ActiveView, curve);
		}

		public static DetailCurve CreatYJKDetailCurve(this Document revDoc, View view, Curve curve)
		{
			return revDoc.Create.NewDetailCurve(view, curve);
		}

		public static ModelCurve CreatHYModelCurve(this Document revDoc, Curve curve)
		{
			return revDoc.Create.NewModelCurve(curve, revDoc.ActiveView.SketchPlane);
		}

		public static ModelLine CreatHYModelLine(this Document revDoc, XYZ sPnt, XYZ ePnt)
		{
			Line line = revDoc.CreatYJKLine(sPnt, ePnt, true);
			Plane plane = new Plane(new XYZ(1.0, 0.0, 0.0), sPnt);
			SketchPlane sketchPlane = SketchPlane.Create(revDoc, plane);
			return revDoc.Create.NewModelCurve(line, sketchPlane) as ModelLine;
		}

		public static ICollection<ElementId> DeleteElement(this Document revitDocument, Element elem)
		{
			new List<ElementId>();
			return revitDocument.Delete(elem.Id);
		}

		public static Wall CreatHYWall(this Document revitDocument, Curve curve, WallType wallType, Level level, double height, double offset, bool flip, bool structural)
		{
			return Wall.Create(revitDocument, curve, wallType.Id, level.Id, height, offset, flip, structural);
		}

		public static Duct CreateHYDuct(this Document document, Connector startConnector, Connector endConnector, DuctType ductType, ElementId levelId)
		{
			Duct duct = document.Create.NewDuct(startConnector, endConnector, ductType);
			Parameter parameter = duct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
			if (parameter != null)
			{
				parameter.Set(levelId);
			}
			return duct;
		}

		public static Duct CreateHYDuct(this Document document, XYZ endPoint, Connector startConnector, DuctType ductType, ElementId levelId)
		{
			Duct duct = document.Create.NewDuct(endPoint, startConnector, ductType);
			Parameter parameter = duct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
			if (parameter != null)
			{
				parameter.Set(levelId);
			}
			return duct;
		}

		public static Duct CreateHYDuct(this Document document, XYZ startPoint, XYZ endPoint, ElementId systemTypeId, DuctType ductType, ElementId levelId)
		{
			Duct duct = document.Create.NewDuct(startPoint, endPoint, ductType);
			Parameter parameter = duct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
			if (parameter != null)
			{
				parameter.Set(levelId);
			}
			Parameter parameter2 = duct.get_Parameter(BuiltInParameter.RBS_DUCT_SYSTEM_TYPE_PARAM);
			if (parameter2 != null)
			{
				parameter2.Set(systemTypeId);
			}
			return duct;
		}

		public static Pipe CreatHYPipe(this Document revitDocument, PipingSystemType pipingSystemType, PipeType pipeType, Level level, XYZ start, XYZ end, double diameter)
		{
			Pipe pipe = Pipe.Create(revitDocument, pipingSystemType.Id, pipeType.Id, level.Id, start, end);
			pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(diameter / 304.8);
			revitDocument.Regenerate();
			return pipe;
		}

		public static Pipe CreatHYPipe(this Document revitDocument, PipeType pipeType, Level level, Connector conn, XYZ end, double diameter)
		{
			Pipe pipe = Pipe.Create(revitDocument, pipeType.Id, level.Id, conn, end);
			pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(diameter / 304.8);
			revitDocument.Regenerate();
			return pipe;
		}

		public static Pipe CopyPipe(Document document)
		{
			IEnumerable<Element> elementByClass = YJKElementFilter.GetElementByClass(typeof(Pipe), document);
			Pipe result = null;
			foreach (Element element in elementByClass)
			{
				if (element != null && element is Pipe && ((Pipe)element).get_Parameter(BuiltInParameter.RBS_PIPE_SLOPE).AsDouble().ToString() == "0" && ((Pipe)element).get_Parameter(-1140334).AsValueString() != "未定义")
				{
					result = (Pipe)element;
					break;
				}
			}
			return result;
		}

		public static View3D CreatHYView3D(this Document doc, XYZ viewDirection)
		{
			View3D view3D = doc.ActiveView as Autodesk.Revit.DB.View3D;
			XYZ xyz = new XYZ(0.0, 0.0, 0.0);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(ViewFamilyType));
			IEnumerable<ViewFamilyType> source = from elem in filteredElementCollector
			let type = elem as Autodesk.Revit.DB.ViewFamilyType
			where type.ViewFamily == 102
			select type;
			ElementId elementId = null;
			if (source.Count<ViewFamilyType>() > 0)
			{
				elementId = source.First<ViewFamilyType>().Id;
			}
			view3D = View3D.CreateIsometric(doc, elementId);
			if (view3D != null)
			{
				XYZ xyz2 = new XYZ(0.0, 1.0, 1.0);
				XYZ xyz3 = new XYZ(0.0, 1.0, -1.0);
				xyz2.AngleTo(xyz3);
				new XYZ(0.0, 1.0, 1.0).AngleTo(new XYZ(0.0, 1.0, -1.0));
				ViewOrientation3D orientation = new ViewOrientation3D(xyz, xyz2, xyz3);
				view3D.SetOrientation(orientation);
			}
			return view3D;
		}

		public static View3D CreatHYSubView3D(this Document doc, XYZ viewDirection, XYZ eye)
		{
			View3D view3D = doc.ActiveView as Autodesk.Revit.DB.View3D;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(ViewFamilyType));
			IEnumerable<ViewFamilyType> source = from elem in filteredElementCollector
			let type = elem as Autodesk.Revit.DB.ViewFamilyType
			where type.ViewFamily == 102
			select type;
			ElementId elementId = null;
			if (source.Count<ViewFamilyType>() > 0)
			{
				elementId = source.First<ViewFamilyType>().Id;
			}
			view3D = View3D.CreateIsometric(doc, elementId);
			if (view3D != null)
			{
				XYZ xyz = new XYZ(-1.0, 1.0, Math.Sqrt(2.0));
				XYZ xyz2 = new XYZ(-1.0, 1.0, -Math.Sqrt(2.0));
				xyz.AngleTo(xyz2);
				new XYZ(0.0, 1.0, 1.0).AngleTo(new XYZ(0.0, 1.0, -1.0));
				ViewOrientation3D orientation = new ViewOrientation3D(eye, xyz, xyz2);
				view3D.SetOrientation(orientation);
			}
			return view3D;
		}

		public static View3D CreatHYView3DSystem(this Document doc, XYZ viewDirection, XYZ eye)
		{
			View3D view3D = doc.ActiveView as Autodesk.Revit.DB.View3D;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(ViewFamilyType));
			IEnumerable<ViewFamilyType> source = from elem in filteredElementCollector
			let type = elem as Autodesk.Revit.DB.ViewFamilyType
			where type.ViewFamily == 102
			select type;
			ElementId elementId = null;
			if (source.Count<ViewFamilyType>() > 0)
			{
				elementId = source.First<ViewFamilyType>().Id;
			}
			view3D = View3D.CreateIsometric(doc, elementId);
			if (view3D != null)
			{
				XYZ xyz = new XYZ(-1.0, 1.0, 2.0);
				XYZ xyz2 = new XYZ(-1.0, 1.0, -1.0);
				xyz.AngleTo(xyz2);
				new XYZ(0.0, 1.0, 1.0).AngleTo(new XYZ(0.0, 1.0, -1.0));
				ViewOrientation3D orientation = new ViewOrientation3D(eye, xyz, xyz2);
				view3D.SetOrientation(orientation);
			}
			return view3D;
		}

		public static void HYSaveOrientationAndLock(this View3D view3D)
		{
			view3D.SaveOrientationAndLock();
		}

		public static void SetYJKSectionBox(this View3D view3D, BoundingBoxXYZ boundingBox)
		{
			view3D.SetSectionBox(boundingBox);
		}

		public static Line CreatYJKLine(this Document doc, XYZ point, XYZ endOrDirection, bool bound)
		{
			Line result;
			if (bound)
			{
				result = Line.CreateBound(point, endOrDirection);
			}
			else
			{
				result = Line.CreateUnbound(point, endOrDirection);
			}
			return result;
		}

		public static Line CreatYJKLine(this Application revitApp, XYZ point, XYZ endOrDirection, bool bound)
		{
			Line result;
			if (bound)
			{
				result = Line.CreateBound(point, endOrDirection);
			}
			else
			{
				result = Line.CreateUnbound(point, endOrDirection);
			}
			return result;
		}

		public static XYZ GetEndPoint(this Curve curve, int index)
		{
			new XYZ(0.0, 0.0, 0.0);
			return curve.GetEndPoint(index);
		}

		public static double GetYJKEndParameter(this Curve curve, int index)
		{
			return curve.GetEndParameter(index);
		}

		public static Reference GetYJKEndPointReference(this Curve curve, int index)
		{
			return curve.GetEndPointReference(index);
		}

		public static SketchPlane CreatYJKSketchPlane(this Document doc, Plane plane)
		{
			return SketchPlane.Create(doc, plane);
		}

		public static void SetYJKProjColorOverrideByElement(this View view, ICollection<ElementId> ids, Color color)
		{
			OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
			overrideGraphicSettings.SetProjectionFillColor(color);
			overrideGraphicSettings.SetProjectionLineColor(color);
			foreach (ElementId elementId in ids)
			{
				view.SetElementOverrides(elementId, overrideGraphicSettings);
			}
		}

		public static void HYRotateElements(this Document doc, ICollection<ElementId> elementsToRotate, Line axis, double angle)
		{
			ElementTransformUtils.RotateElements(doc, elementsToRotate, axis, angle);
		}

		public static void SetYJKVisibility(this Document doc, Category cate, bool bVisible)
		{
			doc.ActiveView.SetVisibility(cate, bVisible);
		}

		public static bool GetYJKVisibility(this Document doc, Category cate)
		{
			return doc.ActiveView.GetVisibility(cate);
		}

		public static void SetYJKVisibility(this View view, Category category, bool visible)
		{
			view.SetVisibility(category, visible);
		}

		public static bool GetYJKVisibility(this View view, Category category)
		{
			return view.GetVisibility(category);
		}

		public static void SetHYProjLineWeightOverrideByElement(this View view, ICollection<ElementId> ids, int weight)
		{
			OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
			overrideGraphicSettings.SetProjectionLineWeight(weight);
			foreach (ElementId elementId in ids)
			{
				view.SetElementOverrides(elementId, overrideGraphicSettings);
			}
		}

		public static void SetYJKProjLinePatternOverrideByElement(this View view, ICollection<ElementId> ids, LinePatternElement linePattern)
		{
			OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
			overrideGraphicSettings.SetProjectionLinePatternId(linePattern.Id);
			foreach (ElementId elementId in ids)
			{
				view.SetElementOverrides(elementId, overrideGraphicSettings);
			}
		}

		public static bool EnergyAnalysis(this Document doc)
		{
			if (YJKElementFilter.GetElementByCategory(doc, BuiltInCategory.OST_MEPSpaces).Count != 0)
			{
				EnergyAnalysisDetailModel.Create(doc, new EnergyAnalysisDetailModelOptions
				{
					Tier = 3
				});
				return true;
			}
			return false;
		}

		public static TextNote GetTextNode(this Document doc, View view, XYZ origin, XYZ baseVec, XYZ upVec, double lineWidth, TextAlignFlags textAlign, string strText)
		{
			TextNoteType textNoteType = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(TextNoteType));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				TextNoteType textNoteType2 = element as TextNoteType;
				if (textNoteType2 != null)
				{
					textNoteType = textNoteType2;
					break;
				}
			}
			double rotation = XYZ.BasisX.AngleOnPlaneTo(baseVec, XYZ.BasisZ);
			TextNoteOptions textNoteOptions = new TextNoteOptions();
			textNoteOptions.Rotation = rotation;
			if ((textAlign & 64) == 64)
			{
				textNoteOptions.HorizontalAlignment = 0;
			}
			else if ((textAlign & 256) == 256)
			{
				textNoteOptions.HorizontalAlignment = 1;
			}
			else
			{
				textNoteOptions.HorizontalAlignment = 2;
			}
			textNoteOptions.TypeId = textNoteType.Id;
			return TextNote.Create(doc, view.Id, origin, lineWidth, strText, textNoteOptions);
		}

		public static TextNote GetTextNode(this Document doc, View view, XYZ origin, XYZ baseVec, XYZ upVec, double lineWidth, TextAlignFlags textAlign, string strText, TextNoteType tnt)
		{
			double rotation = XYZ.BasisX.AngleOnPlaneTo(baseVec, XYZ.BasisZ);
			TextNoteOptions textNoteOptions = new TextNoteOptions();
			textNoteOptions.Rotation = rotation;
			if ((textAlign & 64) == 64)
			{
				textNoteOptions.HorizontalAlignment = 0;
			}
			else if ((textAlign & 256) == 256)
			{
				textNoteOptions.HorizontalAlignment = 1;
			}
			else
			{
				textNoteOptions.HorizontalAlignment = 2;
			}
			textNoteOptions.TypeId = tnt.Id;
			return TextNote.Create(doc, view.Id, origin, lineWidth, strText, textNoteOptions);
		}

		public static TextNote GetTextNode(this Document doc, View view, XYZ origin, XYZ baseVec, XYZ upVec, double lineWidth, TextAlignFlags textAlign, string strText, double width)
		{
			TextNoteType textNoteType = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(TextNoteType));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				TextNoteType textNoteType2 = element as TextNoteType;
				if (textNoteType2 != null)
				{
					textNoteType = textNoteType2;
					break;
				}
			}
			double rotation = XYZ.BasisX.AngleOnPlaneTo(baseVec, XYZ.BasisZ);
			TextNoteOptions textNoteOptions = new TextNoteOptions();
			textNoteOptions.Rotation = rotation;
			if ((textAlign & 64) == 64)
			{
				textNoteOptions.HorizontalAlignment = 0;
			}
			else if ((textAlign & 256) == 256)
			{
				textNoteOptions.HorizontalAlignment = 1;
			}
			else
			{
				textNoteOptions.HorizontalAlignment = 2;
			}
			textNoteOptions.TypeId = textNoteType.Id;
			TextNote textNote = TextNote.Create(doc, view.Id, origin, lineWidth, strText, textNoteOptions);
			textNote.Width = width / 304.8;
			return textNote;
		}

		public static TextNote GetTextNode(this Document doc, View view, XYZ origin, XYZ baseVec, XYZ upVec, double lineWidth, TextAlignFlags textAlign, TextNoteLeaderTypes leaderType, TextNoteLeaderStyles leaderStyle, XYZ leaderEnd, XYZ leaderElbow, string strText)
		{
			TextNoteType textNoteType = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(TextNoteType));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				TextNoteType textNoteType2 = element as TextNoteType;
				if (textNoteType2 != null)
				{
					textNoteType = textNoteType2;
					break;
				}
			}
			double rotation = XYZ.BasisX.AngleOnPlaneTo(baseVec, XYZ.BasisZ);
			TextNoteOptions textNoteOptions = new TextNoteOptions();
			textNoteOptions.Rotation = rotation;
			if ((textAlign & 64) == 64)
			{
				textNoteOptions.HorizontalAlignment = 0;
			}
			else if ((textAlign & 256) == 256)
			{
				textNoteOptions.HorizontalAlignment = 1;
			}
			else
			{
				textNoteOptions.HorizontalAlignment = 2;
			}
			textNoteOptions.TypeId = textNoteType.Id;
			TextNote textNote = TextNote.Create(doc, view.Id, origin, lineWidth, strText, textNoteOptions);
			Leader leader = textNote.AddLeader(leaderType);
			leader.Elbow = leaderElbow;
			leader.End = leaderEnd;
			return textNote;
		}

		public static TextNote CreateTextNoteAutoWrapping(this Document doc, View view, XYZ origin, XYZ vtBase, XYZ vtUp, TextAlignFlags textAlign, string strText, int iWrappingWordCount)
		{
			for (int i = 0; i < strText.Length / iWrappingWordCount; i++)
			{
				strText = strText.Insert((i + 1) * iWrappingWordCount, "\r\n");
			}
			TextNoteType textNoteType = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(TextNoteType));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				TextNoteType textNoteType2 = element as TextNoteType;
				if (textNoteType2 != null)
				{
					textNoteType = textNoteType2;
					break;
				}
			}
			double rotation = XYZ.BasisX.AngleOnPlaneTo(vtBase, XYZ.BasisZ);
			TextNoteOptions textNoteOptions = new TextNoteOptions();
			textNoteOptions.Rotation = rotation;
			if ((textAlign & 64) == 64)
			{
				textNoteOptions.HorizontalAlignment = 0;
			}
			else if ((textAlign & 256) == 256)
			{
				textNoteOptions.HorizontalAlignment = 1;
			}
			else
			{
				textNoteOptions.HorizontalAlignment = 2;
			}
			textNoteOptions.TypeId = textNoteType.Id;
			return TextNote.Create(doc, view.Id, origin, strText, textNoteOptions);
		}

		public static List<double> GetFloorPipeMarkSizes()
		{
			return new List<double>
			{
				1000.0,
				200.0,
				820.0,
				500.0,
				15.0
			};
		}

		public static Bitmap GetImageFromRevit(Document doc, Element elemImg)
		{
			if (elemImg == null || doc == null)
			{
				return null;
			}
			return (doc.GetElementById(elemImg.GetTypeId()) as ImageType).GetImage();
		}

		public static IList<ElementId> GetStackedWallMemberIds(this Wall wall)
		{
			if (wall == null)
			{
				return null;
			}
			return wall.GetStackedWallMemberIds();
		}

		public static Element GetElementByRef(this UIDocument uiDoc, Reference reference)
		{
			if (uiDoc == null || uiDoc.Document == null)
			{
				return null;
			}
			return uiDoc.Document.GetElementByRef(reference);
		}

		public static Element GetElementById(this UIDocument uiDoc, ElementId id)
		{
			return uiDoc.Document.GetElementById(id);
		}

		public static ModelLine CreateModelLine(this Document document, XYZ p1, XYZ p2)
		{
			Plane plane = new Plane((Math.Abs(p1.Z - p2.Z) > 0.01) ? new XYZ(1.0, 0.0, 0.0) : new XYZ(0.0, 0.0, 1.0), p1);
			SketchPlane sketchPlane = SketchPlane.Create(document, plane);
			Line line = Line.CreateBound(p1, p2);
			return document.Create.NewModelCurve(line, sketchPlane) as ModelLine;
		}

		public static void CreateModelLineBox(this Document document, Outline outLine)
		{
			XYZ minimumPoint = outLine.MinimumPoint;
			XYZ maximumPoint = outLine.MaximumPoint;
			document.CreateModelLineBox(minimumPoint, maximumPoint);
		}

		public static void CreateModelLineBox(this Document document, XYZ bottomLeft, XYZ topRight)
		{
			XYZ[] boxPoints = bottomLeft.GetBoxPoints(topRight);
			using (Transaction transaction = new Transaction(document, "CreateModelLineBox"))
			{
				transaction.Start();
				document.CreateModelLine(boxPoints[0], boxPoints[1]);
				document.CreateModelLine(boxPoints[1], boxPoints[2]);
				document.CreateModelLine(boxPoints[2], boxPoints[3]);
				document.CreateModelLine(boxPoints[3], boxPoints[0]);
				document.CreateModelLine(boxPoints[4], boxPoints[5]);
				document.CreateModelLine(boxPoints[5], boxPoints[6]);
				document.CreateModelLine(boxPoints[6], boxPoints[7]);
				document.CreateModelLine(boxPoints[7], boxPoints[4]);
				document.CreateModelLine(boxPoints[0], boxPoints[4]);
				document.CreateModelLine(boxPoints[1], boxPoints[5]);
				document.CreateModelLine(boxPoints[2], boxPoints[6]);
				document.CreateModelLine(boxPoints[3], boxPoints[7]);
				transaction.Commit();
			}
		}

		public static IEnumerable<T> GetElements<T>(this Document document) where T : Element
		{
			return new FilteredElementCollector(document).OfClass(typeof(T)).ToElements().Cast<T>();
		}

		public static IEnumerable<Element> GetElements<T>(this Document document, XYZ searchPoint, double searchBoxLength) where T : Element
		{
			double num = searchBoxLength / 2.0;
			XYZ xyz = new XYZ(searchPoint.X - num, searchPoint.Y - num, searchPoint.Z - num);
			XYZ xyz2 = new XYZ(searchPoint.X + num, searchPoint.Y + num, searchPoint.Z + num);
			BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(new Outline(xyz, xyz2));
			return new FilteredElementCollector(document).OfClass(typeof(T)).WherePasses(boundingBoxIntersectsFilter).ToElements();
		}

		public static IEnumerable<Element> GetElements(this Document document, XYZ searchPoint, double searchBoxLength)
		{
			double num = searchBoxLength / 2.0;
			XYZ xyz = new XYZ(searchPoint.X - num, searchPoint.Y - num, searchPoint.Z - num);
			XYZ xyz2 = new XYZ(searchPoint.X + num, searchPoint.Y + num, searchPoint.Z + num);
			BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(new Outline(xyz, xyz2));
			return new FilteredElementCollector(document).WherePasses(boundingBoxIntersectsFilter).ToElements();
		}

		public static bool HasLinkDocuments(this Document document)
		{
			IEnumerable<RevitLinkInstance> elements = document.GetElements<RevitLinkInstance>();
			return elements != null && elements.Any<RevitLinkInstance>();
		}

		public static IEnumerable<Document> GetLinkDocuments(this Document document)
		{
			IEnumerable<RevitLinkInstance> elements = document.GetElements<RevitLinkInstance>();
			if (elements == null || !elements.Any<RevitLinkInstance>())
			{
				return null;
			}
			return from ins in elements
			select ins.GetLinkDocument();
		}

		public static Document GetLinkDocument(this Document document, ElementId elementIdInLinkDocument)
		{
			IEnumerable<Document> linkDocuments = document.GetLinkDocuments();
			if (linkDocuments != null)
			{
				return linkDocuments.FirstOrDefault((Document doc) => doc.Contains(elementIdInLinkDocument));
			}
			return null;
		}

		public static bool Contains(this Document doc, ElementId elementId)
		{
			return doc.GetElementById(elementId) != null;
		}

		public static Element GetElementByRef(this Document document, Reference reference)
		{
			if (document == null || reference == null)
			{
				return null;
			}
			ElementId linkedElementId = reference.LinkedElementId;
			if (linkedElementId == ElementId.InvalidElementId)
			{
				return document.GetElementById(reference.ElementId);
			}
			Document linkDocument = document.GetLinkDocument(linkedElementId);
			if (linkDocument != null)
			{
				return linkDocument.GetElementById(linkedElementId);
			}
			return null;
		}

		public static XYZ[] GetBoxPoints(this XYZ bottomLeft, XYZ topRight)
		{
			return new XYZ[]
			{
				bottomLeft,
				new XYZ(bottomLeft.X, topRight.Y, bottomLeft.Z),
				new XYZ(topRight.X, topRight.Y, bottomLeft.Z),
				new XYZ(topRight.X, bottomLeft.Y, bottomLeft.Z),
				new XYZ(bottomLeft.X, bottomLeft.Y, topRight.Z),
				new XYZ(bottomLeft.X, topRight.Y, topRight.Z),
				topRight,
				new XYZ(topRight.X, bottomLeft.Y, topRight.Z)
			};
		}

		public static ElementSet GetNewGrids(this Document doc, CurveArray curves)
		{
			ElementSet elementSet = new ElementSet();
			foreach (object obj in curves)
			{
				Curve curve = (Curve)obj;
				Grid grid;
				if (curve is Line)
				{
					grid = Grid.Create(doc, curve as Line);
				}
				else
				{
					grid = Grid.Create(doc, curve as Arc);
				}
				grid.ExtendToAllLevels();
				elementSet.Insert(grid);
			}
			return elementSet;
		}

		public static Grid HyNewGrid(this Document doc, Arc arc)
		{
			Grid result = null;
			CurveArray curves = new CurveArray();
			ElementSet newGrids = doc.GetNewGrids(curves);
			if (newGrids.Size > 0)
			{
				ElementSetIterator elementSetIterator = newGrids.ForwardIterator();
				elementSetIterator.Reset();
				if (elementSetIterator.MoveNext())
				{
					result = ((elementSetIterator.Current as Element) as Grid);
				}
			}
			return result;
		}

		public static Grid HyNewGrid(this Document doc, Line line)
		{
			Grid result = null;
			CurveArray curveArray = new CurveArray();
			curveArray.Append(line);
			ElementSet newGrids = doc.GetNewGrids(curveArray);
			if (newGrids.Size > 0)
			{
				ElementSetIterator elementSetIterator = newGrids.ForwardIterator();
				elementSetIterator.Reset();
				if (elementSetIterator.MoveNext())
				{
					result = ((elementSetIterator.Current as Element) as Grid);
				}
			}
			return result;
		}

		public static Level HyNewLevel(this Document doc, double dElevation)
		{
			return Level.Create(doc, dElevation);
		}

		public static ElementId CreateMultiSegmentGrid(Document document, ElementId typeId, CurveLoop curveLoop, ElementId sketchPlaneId)
		{
			ElementId elementId = MultiSegmentGrid.Create(document, typeId, curveLoop, sketchPlaneId);
			RevitDocumentExtension.ExtendToAllLevels(document.GetElement(elementId) as MultiSegmentGrid, document);
			return elementId;
		}

		private static void ExtendToAllLevels(MultiSegmentGrid multiSegmentGrid, Document document)
		{
			foreach (ElementId elementId in multiSegmentGrid.GetGridIds())
			{
				try
				{
					(document.GetElement(elementId) as Grid).ExtendToAllLevels();
				}
				catch (Exception)
				{
				}
			}
		}

		private static void GetVerticalRange(Document doc, ref double bottom, ref double top)
		{
			bottom = double.MaxValue;
			top = double.MinValue;
			new List<Level>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Level)).ToElements())
			{
				double elevation = (element as Level).Elevation;
				if (RevitDocumentExtension.LessThan(elevation, bottom))
				{
					bottom = elevation;
				}
				if (RevitDocumentExtension.LessThan(top, elevation))
				{
					top = elevation;
				}
			}
		}

		private static bool LessThan(double val1, double val2)
		{
			return val1 - val2 < -1E-09;
		}

		private const double _epsDouble = 1E-09;
	}
}
